#pragma once

#include <iostream>
#include <string>
#include <list>
#include <memory>
#include <algorithm>
#include <sys/types.h>
#include <sys/socket.h>

#include "InetAddr.hpp"
#include "Log.hpp"
#include "Mutex.hpp"

using namespace LogMudule;
using namespace LockModule;

// 基类-抽象类
class UserInterface
{
public:
    virtual ~UserInterface() = default;
    virtual void SendTo(int sockfd, const std::string &message) = 0;
    virtual bool operator==(const InetAddr &u) = 0;
    virtual std::string Id() = 0;
};
// 派生类
class User : public UserInterface
{
public:
    User(const InetAddr& id)
        : _id(id)
    {}
    void SendTo(int sockfd, const std::string &message) override
    {
        LOG(LogLevel::DEBUG) << "send message to " << _id.Addr() << " info: " << message;
        // 发送消息
        int n = ::sendto(sockfd, message.c_str(), message.size(), 0, _id.NetAddr(), _id.NetAddrLen());
        (void)n;
    }
    bool operator==(const InetAddr& u) override
    {
        return _id == u;
    }
    std::string Id() override
    {
        return _id.Addr();
    }
    ~User()
    {}
private:
    InetAddr _id;
};

// 对用户消息进行路由
// UserManager 把所有的用户先管理起来！
// 观察者模式：observer
class UserManager
{
public:
    UserManager()
    {}
    // 增加用户
    void AddUser(InetAddr& id)
    {
        LockGuard lockguard(_mutex);    // 加锁
        // 如果用户存在就不在添加，直接返回
        for(auto& user : _on_line_user)
        {
            if(*user == id) 
            {
                LOG(LogLevel::INFO) << id.Addr() << "用户已经存在";
                return ;
            }
        }
        LOG(LogLevel::INFO) << " 新增该用户: " <<  id.Addr(); 
        _on_line_user.push_back(std::make_shared<User>(id));
        PrintUser();
    }
    // 移除用户
    void DelUser(InetAddr& id)
    {
        auto pos = std::remove_if(_on_line_user.begin(), _on_line_user.end(), [&id](std::shared_ptr<UserInterface> &user)
            {
                return *user == id;
            });
        _on_line_user.erase(pos, _on_line_user.end());
        PrintUser();
    }
    // 路由，多路转发消息
    void Router(int sockfd, const std::string& message)
    {
        LockGuard lockguard(_mutex);    // 加锁
        for(auto& user : _on_line_user)
        {
            user->SendTo(sockfd, message);
        }
    }
    void PrintUser()
    {
        for(auto user : _on_line_user)
        {
            LOG(LogLevel::DEBUG) << "在线用户-> " << user->Id();
        }
    }
    ~UserManager()
    {}
private:
    std::list<std::shared_ptr<UserInterface>> _on_line_user;    // 所有在线用户
    Mutex _mutex;   // 锁
};